package com.wejoy.video.middle.station.data.service.overtime.impl;

import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.wejoy.video.middle.station.data.domain.overtime.OvertimePoint;
import com.wejoy.video.middle.station.data.domain.system.SysCarmera;
import com.wejoy.video.middle.station.data.domain.system.SysDept;
import com.wejoy.video.middle.station.data.domain.system.SysUser;
import com.wejoy.video.middle.station.data.enums.dict.EnumDeptType;
import com.wejoy.video.middle.station.data.enums.dict.EnumPointConfigStatus;
import com.wejoy.video.middle.station.data.enums.dict.EnumStatus;
import com.wejoy.video.middle.station.data.exception.BusinessException;
import com.wejoy.video.middle.station.data.mapper.overtime.IOvertimeInfoMapper;
import com.wejoy.video.middle.station.data.domain.overtime.OvertimeInfo;
import com.wejoy.video.middle.station.data.service.common.IIdWorkerService;
import com.wejoy.video.middle.station.data.service.evs.IEvsHttpService;
import com.wejoy.video.middle.station.data.service.overtime.IOvertimeInfoService;
import com.wejoy.video.middle.station.data.service.overtime.IOvertimePointService;
import com.wejoy.video.middle.station.data.service.system.ISysDeptService;
import com.wejoy.video.middle.station.data.util.DateUtils;
import com.wejoy.video.middle.station.data.util.WJAssert;
import com.wejoy.video.middle.station.data.vo.api.BusinessPointConfigVO;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 加班详情
 *
 * @author miracle_j
 * @date 2024年04月22日 11:11:52
 */
@Service
public class OvertimeInfoServiceImpl implements IOvertimeInfoService {
    @Autowired
    private IOvertimeInfoMapper overtimeInfoMapper;
    @Autowired
    private IIdWorkerService idWorkerService;
    @Autowired
    private ISysDeptService sysDeptService;
    @Autowired
    private IEvsHttpService evsHttpService;
    @Autowired
    private IOvertimePointService overtimePointService;
    //        System.out.println(getPointConfig("zone_safety", "human_intrusion_detection", 200010716, token));
    private static final String SCENETYPE="zone_safety";
    private static final String ABILITYTYPE="human_intrusion_detection";

    @Override
    public void save(OvertimeInfo req, SysUser user) {
        req.setOperator(user.getName());
        OvertimeInfo overtimeInfo = getOneByDeptId(req.getDeptId());
        if(!ObjectUtils.isEmpty(overtimeInfo)){
            req.setId(overtimeInfo.getId());
        }
        if (null == req.getId()) {
            long timeDifference = DateUtils.getTimeDifference(req.getBeginTime());
            Boolean effective_immediately=timeDifference<=5;
            //查询部门信息
            SysDept deptServiceOneById = sysDeptService.getOneById(req.getDeptId());
            //部门信息为空或者部门不是营业厅
//            if(deptServiceOneById==null|| !StringUtils.equals(deptServiceOneById.getDeptType().toString(), EnumDeptType.DEPT_BUSINESS_HALL.getCode().toString())){
//                throw new BusinessException("加班部门只能设置营业厅！");
//            }
            req.setId(idWorkerService.getNextId());
            if(req.getStatus().equals(EnumStatus.AUDIT.getCode())&&effective_immediately){
                closeAbility(req);
            }
            insertSelective(req);
        } else {
            //如果只是打开开关
            if(overtimeInfo.getStatus().equals(EnumStatus.NEW.getCode())&&req.getStatus().equals(EnumStatus.AUDIT.getCode())){
                closeAbility(req);
                req.setDataStatus(EnumPointConfigStatus.OVERTIME_HOURS.getCode());
            }
            //如果关闭开关
            if(overtimeInfo.getStatus().equals(EnumStatus.AUDIT.getCode())&&req.getStatus().equals(EnumStatus.NEW.getCode())){
                openAbility(overtimeInfo);
                req.setDataStatus(EnumPointConfigStatus.OVERTIME_END.getCode());
            }
            //如果是加班中修改时间。先恢复算法，在按新加班时间关闭
            if(overtimeInfo.getStatus().equals(EnumStatus.AUDIT.getCode())&&req.getStatus().equals(EnumStatus.AUDIT.getCode())
                    &&(!req.getBeginTime().equals(overtimeInfo.getBeginTime())||!req.getEndTime().equals(overtimeInfo.getEndTime()))){
                openAbility(overtimeInfo);
                closeAbility(req);
            }
            updateSelectiveById(req);
        }
    }

    /**
     * 关闭算法能力
     * @param req
     */
    @Override
    public void closeAbility(OvertimeInfo req) {
        List<Long> points=new ArrayList<>();
        //查询部门下点位
        JSONObject points1 = evsHttpService.getPoints(evsHttpService.getToken(), 90, 1, req.getDeptId().intValue(),null,null);
        List<SysCarmera> carmeras = JSONArray.parseArray(points1.getString("data"), SysCarmera.class);
        List<Long> collect = carmeras.stream()
                .map(SysCarmera::getPointId)
                .collect(Collectors.toList());
        points.addAll(collect);
        //查询原先算法先备份
        points.forEach(item->{
            JSONObject pointConfig = evsHttpService.getPointConfig(SCENETYPE, ABILITYTYPE, item.intValue(), evsHttpService.getToken());
            if(!ObjectUtils.isEmpty(pointConfig)){
                BusinessPointConfigVO businessPointConfigVO = JSONObject.parseObject(pointConfig.toJSONString(), BusinessPointConfigVO.class);
                OvertimePoint overtimePoint = new OvertimePoint();
                overtimePoint.setPointId(item);
                overtimePoint.setPointConfigEvs(JSONObject.toJSONString(businessPointConfigVO));
                overtimePoint.setOverTimeId(req.getId());
                overtimePointService.insertSelective(overtimePoint);
                int dayOfWeekNumber = DateUtils.getDayOfWeekNumber();
                List<Integer> objects = new ArrayList<>();
                objects.add(item.intValue());
                businessPointConfigVO.setPointIds(objects);
                List<BusinessPointConfigVO.ConfigBean.EffectiveTimeBean> effectiveTime = businessPointConfigVO.getConfig().getEffectiveTime();
                if(!CollectionUtils.isEmpty(effectiveTime)){
                    List<BusinessPointConfigVO.ConfigBean.EffectiveTimeBean> result = effectiveTime.stream()
                            .filter(effItem -> effItem.getDayOfWeek() != dayOfWeekNumber)
                            .collect(Collectors.toList());
                    businessPointConfigVO.getConfig().setEffectiveTime(result);
                    evsHttpService.businessHallPointConfig(SCENETYPE, ABILITYTYPE, businessPointConfigVO, evsHttpService.getToken());
                    req.setDataStatus(EnumPointConfigStatus.OVERTIME_HOURS.getCode());
                }
            }
        });
    }

    @Override
    public void openAbility(OvertimeInfo req) {
        OvertimePoint overtimePoint = new OvertimePoint();
        overtimePoint.setOverTimeId(req.getId());
        List<OvertimePoint> list = overtimePointService.getList(overtimePoint);
        list.forEach(item->{
            List<Integer> objects = new ArrayList<>();
            objects.add(item.getPointId().intValue());
            BusinessPointConfigVO businessPointConfigVO = JSONObject.parseObject(item.getPointConfigEvs(), BusinessPointConfigVO.class);
            businessPointConfigVO.setPointIds(objects);
            evsHttpService.businessHallPointConfig(SCENETYPE, ABILITYTYPE, businessPointConfigVO, evsHttpService.getToken());
        });
    }

    @Override
    public int insertSelective(OvertimeInfo req) {
        if(req.getId()==null){
            req.setId(idWorkerService.getNextId());
        }
        req.setStatus(EnumStatus.NEW.getCode());
        checkStringLength(req, false);
        return overtimeInfoMapper.insertSelective(req);
    }

    @Override
    public int updateSelectiveById(OvertimeInfo overtimeInfo) {
        WJAssert.notNull(overtimeInfo, "入参对象不能为空");
        WJAssert.notNull(overtimeInfo.getId(), "id参数错误");
        OvertimeInfo where = new OvertimeInfo();
        where.setId(overtimeInfo.getId());
        return overtimeInfoMapper.updateSelective(overtimeInfo, where);
    }

    @Override
    public int getCount(OvertimeInfo overtimeInfo) {
        checkStringLength(overtimeInfo, true);
        return overtimeInfoMapper.getCount(overtimeInfo);
    }

    @Override
    public OvertimeInfo getOneById(Long id) {
        WJAssert.notNull(id, "id参数错误");
        OvertimeInfo where = new OvertimeInfo();
        where.setId(id);
        return overtimeInfoMapper.getOne(where);
    }

    @Override
    public OvertimeInfo getOneByDeptId(Long id) {
        WJAssert.notNull(id, "id参数错误");
        OvertimeInfo where = new OvertimeInfo();
        where.setDeptId(id);
        return overtimeInfoMapper.getOne(where);
    }

    @Override
    public List<OvertimeInfo> getList(OvertimeInfo overtimeInfo) {
        return overtimeInfoMapper.getList(overtimeInfo);
    }

    @Override
    public List<OvertimeInfo> getPageList(OvertimeInfo overtimeInfo) {
        checkStringLength(overtimeInfo, true);
        return overtimeInfoMapper.getPageList(overtimeInfo);
    }

    @Override
    public void audit(Long id, String operator) {
        OvertimeInfo req = new OvertimeInfo();
        req.setId(id);
        req.setOperator(operator);
        req.setStatus(EnumStatus.AUDIT.getCode());
        updateSelectiveById(req);
    }

    @Override
    public void unaudit(Long id, String operator) {
        OvertimeInfo req = new OvertimeInfo();
        req.setId(id);
        req.setOperator(operator);
        req.setStatus(EnumStatus.NEW.getCode());
        updateSelectiveById(req);
    }

    @Override
    public void delete(Long id, String operator) {
        OvertimeInfo req = new OvertimeInfo();
        req.setId(id);
        req.setOperator(operator);
        req.setStatus(EnumStatus.DEL.getCode());
        updateSelectiveById(req);
    }

    /**
     * 参数校验注解默认使用的方法
     */
    private void checkStringLength(OvertimeInfo overtimeInfo, boolean nullAble) {
        WJAssert.notNull(overtimeInfo, "入参对象不能为空");
        WJAssert.notNull(overtimeInfo.getDeptId(), "部门id不合法!");
        WJAssert.limitMaxLength(overtimeInfo.getBeginTime(), true, 32, "加班开始时间不合法!");
        WJAssert.limitMaxLength(overtimeInfo.getEndTime(), true, 32, "加班结束时间不合法!");
        WJAssert.limitMaxLength(overtimeInfo.getOperator(), true, 100, "操作者不合法!");
        WJAssert.limitMaxLength(overtimeInfo.getRemark(), true, 255, "备注不合法!");
    }
}
